import AsyncStorage from '@react-native-async-storage/async-storage';
import { compressToUTF16, decompressFromUTF16 } from 'lz-string';
import { GameState } from '../contexts/GameContext';

const SAVE_KEY = 'YONGLE_GAME_SAVES';

type SaveSlot = {
  id: string;
  timestamp: number;
  preview: {
    faction: string;
    turn: number;
    resources: number;
    units: number;
  };
  data: GameState | string; // 支持压缩字符串
  compressed?: boolean;
};

class SaveSystem {
  static async listSaves(): Promise<SaveSlot[]> {
    try {
      const savesJson = await AsyncStorage.getItem(SAVE_KEY);
      if (!savesJson) return [];
      
      try {
        const saves: unknown = JSON.parse(savesJson);
        if (!Array.isArray(saves)) return [];
        
        return saves.map(save => {
          if (typeof save !== 'object' || save === null) return null;
          
          const {id, timestamp, preview, data, compressed} = save as Partial<SaveSlot>;
          if (!id || !timestamp || !preview) return null;
          
          return {
            id,
            timestamp,
            preview,
            data: compressed ? 'compressed' : data,
            compressed
          };
        }).filter((save): save is SaveSlot => save !== null);
      } catch (error) {
        return [];
      }
    } catch (error) {
      return [];
    }
  }

  static async saveGame(state: GameState): Promise<{success: boolean; error?: string}> {
    try {
      // 增强的游戏状态验证
      const requiredFields = [
        'currentPlayer', 'players', 'gamePhase', 
        'resources', 'units', 'effects'
      ];
      
      // 更安全的类型检查
      for (const field of requiredFields) {
        const fieldValue = state[field as keyof typeof state];
        if (fieldValue === undefined || fieldValue === null) {
          throw new Error(`Invalid game state: missing ${field}`);
        }
      }

      // 验证玩家数据
      if (!state.currentPlayer?.id || !state.currentPlayer?.faction?.id) {
        throw new Error('Invalid player data');
      }

      // 验证单位数据
      if (!state.units || state.units.some(unit => !unit?.id || !unit?.owner)) {
        throw new Error('Invalid units data');
      }
      
      const saves = await this.listSaves();
      const newSave: SaveSlot = {
        id: Date.now().toString(),
        timestamp: Date.now(),
        preview: {
          faction: state.currentPlayer.faction.name,
          turn: state.timestamp ? Math.floor((Date.now() - state.timestamp) / 60000) : 0,
          resources: state.resources ? Object.values(state.resources).reduce<number>((a, b) => a + (b || 0), 0) : 0,
          units: state.units?.length || 0
        },
        data: {
          ...state,
          timestamp: Date.now(),
          version: '1.0' // 添加版本控制
        }
      };

      // 验证存档数据
      if (!newSave.data.currentPlayer || !newSave.data.units) {
        throw new Error('Failed to create valid save data');
      }

      // 验证资源数据
      const resources = newSave.data.resources;
      if (resources.grain < 0 || resources.horses < 0 || 
          resources.gunpowder < 0 || resources.dragonVein < 0) {
        throw new Error('Invalid resources data');
      }

      // 压缩存档数据
      const compressedSave = {
        ...newSave,
        data: compressToUTF16(JSON.stringify(newSave.data)),
        compressed: true
      };

      // 保留最近5个存档
      const updatedSaves = [compressedSave, ...saves].slice(0, 5);
      await AsyncStorage.setItem(SAVE_KEY, JSON.stringify(updatedSaves));
      return {success: true};
    } catch (error) {
      return {success: false, error: 'Failed to save game'};
    }
  }

  static async loadGame(saveId: string): Promise<{state: GameState | null; error?: string}> {
    try {
      const saves = await this.listSaves();
      const save = saves.find(s => s.id === saveId);
      
      if (!save) {
        return {state: null, error: 'Save not found'};
      }

      // 处理压缩数据
      let rawData = save.data;
      if (save.compressed && typeof rawData === 'string') {
        try {
          const decompressed = decompressFromUTF16(rawData);
          if (!decompressed) {
            throw new Error('Failed to decompress save data');
          }
          rawData = JSON.parse(decompressed);
        } catch (error) {
          throw new Error(`Decompression failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
      }

      // 版本兼容性处理
      let gameState;
      if (typeof rawData === 'string') {
        try {
          gameState = JSON.parse(rawData) as GameState;
        } catch (error) {
          throw new Error(`Invalid JSON data: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
      } else {
        gameState = rawData;
      }
      if (!gameState.version || gameState.version !== '1.0') {
        // 数据迁移逻辑
        gameState = this.migrateSaveData(gameState);
      }

      // 验证加载的数据
      if (!gameState.currentPlayer || !gameState.units) {
        throw new Error('Invalid save data');
      }

      return {state: gameState};
    } catch (error) {
      return {state: null, error: 'Failed to load game'};
    }
  }

  private static migrateSaveData(oldData: unknown): GameState {
    // 类型检查
    if (typeof oldData !== 'object' || oldData === null) {
      throw new Error('Invalid old data format');
    }

    // 安全的类型转换
    const data = oldData as Partial<GameState>;
    
    // 数据迁移
    const migratedData: GameState = {
      currentPlayer: data.currentPlayer || {
        id: '',
        name: '',
        faction: {
          id: '',
          name: '',
          color: '',
          advantages: ''
        },
        isCommander: false
      },
      players: data.players || [],
      gamePhase: data.gamePhase || 'setup',
      resources: data.resources || {
        grain: 0,
        horses: 0,
        gunpowder: 0,
        dragonVein: 0
      },
      units: data.units || [],
      effects: data.effects || [],
      timestamp: data.timestamp || Date.now(),
      version: '1.0'
    };

    return migratedData;
  }

  static async deleteSave(saveId: string): Promise<boolean> {
    try {
      const saves = await this.listSaves();
      const updatedSaves = saves.filter(s => s.id !== saveId);
      await AsyncStorage.setItem(SAVE_KEY, JSON.stringify(updatedSaves));
      return true;
    } catch (error) {
      return false;
    }
  }
}

export default SaveSystem;
